package org.dairy.farms.dao.generic;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dairy.farms.dao.exception.PersistenceException;
import org.dairy.farms.dao.generic.DAO;
import org.dairy.farms.dao.persistence.BasePersistence;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: gduggira
 * Date: Jun 9, 2011
 * Time: 5:46:40 PM
 */
public abstract class AbstractDAOImpl<T, ID extends Serializable> implements DAO<T, ID> {
    protected static final Log logger = LogFactory.getLog(AbstractDAOImpl.class);
    protected static final String SCHEMA_NAME = "ggov";

    protected Class<T> persistentClass;

    @Autowired
    protected BasePersistence<T> basePersistence;

    public AbstractDAOImpl() {
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public T findById(ID id) throws PersistenceException {
        return basePersistence.load(getPersistentClass(), id);
    }

    public T getById(ID id) throws PersistenceException {
        return basePersistence.get(getPersistentClass(), id);
    }

    /*
     * Return object added for the sake of mockito as it expects some return object when mock the method
     */
    public T create(T object) throws PersistenceException {
        basePersistence.save(object);
        return object;
    }

    /*
     * Return object added for the sake of mockito as it expects some return object when mock the method
     */

    public void update(T object) throws PersistenceException {
        basePersistence.update(object);
    }

    public void delete(T object) throws PersistenceException {
        basePersistence.delete(object);
    }

    /**
     * Utility method expected to be really used only by the impl DAOs/subclasses.
     *
     * @param propertyName
     * @param value
     * @param <T>
     * @return
     */
    public <T> List<T> findByProperty(String propertyName, Object value) throws PersistenceException {
        return basePersistence.findByProperty(getPersistentClass(), propertyName, value);
    }

    /**
     * Utility method to load all the objects of the <code>persistentClass</code> type.
     * Will load all the entities from the table.s
     *
     * @return
     */
    public List<T> loadAllObjects() throws PersistenceException {
        return basePersistence.loadAll(getPersistentClass());
    }

    protected Class<T> getPersistentClass() {
        return persistentClass;
    }

    public void setBasePersistence(BasePersistence basePersistence) {
        this.basePersistence = basePersistence;
    }
}

